<?php
/**
 * 文件操作类
 *
 * @author seraph.liujb 2009.4.28
 */
/*
 $params = array(
 //应用模块名称
 'name'=>'UploadFiles/user',
 );
 $f = Common_File::factory('Image',$params);
 //建立图片
 $ui = $f->create('temp/01.jpg');
 var_dump($ui);

 //处理水印，如来源图片宽度1/4小于50，则强制不加水印
 $params = array(
 //水印文件，默认为UploadFiles/Images/waterLogo.gif
 //            'watermarkFile'=>'UploadFiles/Images/waterLogo.gif',
 //水印位置，0-9，默认为9，其它值为随机位置
 'watermarkPosi'=>10,
 );
 $f->setParams($params);
 $ui = $f->watermark($f->getDestFile());
 var_dump($ui);

 //取得目标文件的绝对路径
 $this->view->file = $f->getDestFile();
 //取得目标文件的相对路径，一般用于URL
 $this->view->fileUrl = $f->getDestFileUrl();

 //生成缩略图
 $params    = array(
 //指定缩略图文件名称，默认为：thumb_width_height_imageFilename.jpg
 //            'thumbFilename'=>'thumb.xxx',
 //指定缩略图文件前缀，默认为：thumb_
 //            'thumbPrefix'=>'sss_',
 //缩略图宽高
 'thumbWidth'=>200,
 'thumbHeight'=>200,
 //是否切割
 'isCutThumb'=>true,
 //是否加水印
 'isWatermark'=>true,
 //            'watermarkFile'=>'UploadFiles/Images/waterLogo.gif',
 //            'watermarkPosi'=>9,
 );
 $f->setParams($params);
 $ui = $f->thumbnail($f->getDestFile());
 var_dump($ui);

 //取得缩略图文件的绝对路径
 $this->view->thumbFile = $f->getThumbFile();
 //取得缩略图文件的相对路径，用于URL
 $this->view->thumbFileUrl = $f->getThumbFileUrl();

 //兼容性返回，create/watermark/thumbnail后，返回数组
 $ui = array(
 'name' => '01.jpg', //来源文件名称
 'type' => 'jpg', //来源图片类型
 'size' => 20672, //来源图片大小
 'savePath' => 'UploadFiles/user/53/11/cb5/', //处理后图片路径
 'saveName' => '01-1248330502', //处理后图片名称
 'extension' => 'jpg', //处理后图片后缀名称
 'hash' => 'c938b356c06842ac8a610adbcf16e7b9', //处理后图片hash值
 'uploadTime' => 1248330502, //图片处理时间
 );


 */

class Common_File_Image extends Common_File_Abstract
{

	/**
	 * __construct
	 *
	 * @param array $params
	 * host 所在服务器名称，例：http://img01.domain.com/
	 * dir 文件处理目录名，一般用来指定相对根目录，所有文件处理都在该目录及其子目录内
	 * name 文件处理类型名称，不同的应用模块使用不同的名称，如：user company
	 * explode 文件名所生成分布路径的分割数列，默认为：2,2,3
	 */
	public function __construct($params = array())
	{
		parent::__construct($params);
		//初始化参数
		if (is_null($params['dir'])) {
			$this->_dir = ROOT_PATH . '/public/';
		}
	}

	/**
	 * Enter description here...
	 *
	 * @param string $sour
	 * @return array
	 */
	public function create($sour)
	{
		parent::create($sour);
		//兼容性返回$ui
		return $this->getReturnFromDest();
	}

	/**
	 * 兼容性返回值，返回$ui数组，为文件复制及水印准备
	 *
	 * @return array
	 */
	public function getReturnFromDest()
	{
		$pSourFile = pathinfo($this->_sourFile);
		$pDestFile = pathinfo($this->getDestFile());
		$ui = array(
            'name'=>$pSourFile['basename'],
            'type'=>$pSourFile['extension'],
            'size'=>filesize($this->getDestFile()),
            'savePath'=>$this->getDestFilepath(),
            'saveName'=>$pDestFile['filename'],
            'extension'=>$pDestFile['extension'],
            'hash'=>md5_file($this->getDestFile()),
            'uploadTime'=>time(),
		);
		return $ui;
	}

	/**
	 * 兼容性返回值，返回$ui数组，为文件缩略准备
	 *
	 * @return array
	 */
	public function getReturnFromThumb()
	{
		$pSourFile = pathinfo($this->_sourFile);
		$pThumbFile = pathinfo($this->getThumbFile());
		$ui = array(
            'name'=>$pSourFile['basename'],
            'type'=>$pSourFile['extension'],
            'size'=>filesize($this->getThumbFile()),
            'savePath'=>$this->getDestFilepath(),
            'saveName'=>$pThumbFile['filename'],
            'extension'=>$pThumbFile['extension'],
            'hash'=>md5_file($this->getThumbFile()),
            'uploadTime'=>time(),
		);
		return $ui;
	}

	/**
	 * 获取目标文件URL地址，绝对路径
	 *
	 * @return string
	 */
	public function getDestFileUrl()
	{
		return $this->_host . '/' . $this->getDestFilepath() . $this->getDestFilename();
	}

	/**
	 * 待处理文件的mime值
	 *
	 * @var string _mime
	 */
	protected $_mime;

	/**
	 * @var $_isWatermark 是否加水印
	 * @var $_watermarkFile 水印图片文件路径
	 * @var $_watermarkPosi 水印在目标图片的位置，默认为9
	 */
	protected $_isWatermark = false;
	protected $_watermarkFile = 'UploadFiles/Images/waterLogo.gif';
	protected $_watermarkPosi = 9;

	/**
	 * 给目标图片加水印图片，如目标图片宽的1/4小于100，则强制不加水印
	 *
	 * @param string $file 目标图片全路径名称
	 * @return array
	 */
	public function watermark($file)
	{
		//判断目标文件可读写
		if (!file_exists($file)) {
			throw new Exception('目标文件不存在！' . $file);
		}
		if (!is_readable($file)) {
			throw new Exception('目标文件没有读取权限！' . $file);
		}
		if (!is_writable($file)) {
			throw new Exception('目标文件没有写入权限！' . $file);
		}
		//获取目标图片信息
		$imageSize = getimagesize($file);
		$this->_mime = $imageSize['mime'];
		//取得水印图
		if(!file_exists($this->_watermarkFile)){
			throw new Exception('水印图片无效！' . $this->_watermarkFile);
		}
		$watermarkInfo = getimagesize($this->_watermarkFile);
		$water_w = $watermarkInfo[0];
		$water_h = $watermarkInfo[1];
		//取得水印图片资源
		$watermarkReso = $this->getImageReso($this->_watermarkFile);
		//取得目标图片资源
		$fileReso = $this->getImageReso($file);
		//生成水印位置参数
		list($posX,$posY,$w,$h)=$this->maskGetXY($water_w,$water_h,$this->_watermarkPosi,$fileReso);
		//目标图片宽的1/4小于50，则强制不加水印
		$_water_w = $w/4;
		if ($_water_w>=50) {
			if ($_water_w > $water_w) {
				$_water_w = $water_w;
				$_water_h = $water_h;
			}
			else {
				$_water_h = $_water_w*$water_h/$water_w;
			}
			list($posX,$posY,$w,$h)=$this->maskGetXY($_water_w,$_water_h,$this->_watermarkPosi,$fileReso);

			$newImage=imagecreate($_water_w,$_water_h);
			imagecopyresampled($newImage,$watermarkReso,0,0,0,0,$_water_w,$_water_h,$water_w,$water_h);
			imagealphablending($fileReso, true);
			//拷贝水印到目标文件
			imagecopy($fileReso, $newImage, $posX, $posY, 0, 0, $_water_w,$_water_h);
			//生成已加水印图片
			$this->newImage($fileReso,$file);
		}
		//兼容性返回$ui
		return $this->getReturnFromDest();
	}

	/**
	 * @var $_thumbWidth 缩略图片宽
	 * @var $_thumbHeight 缩略图片高
	 * @var $_isCuthumb 是否切割缩略图
	 */
	protected $_thumbWidth = 100;
	protected $_thumbHeight = 100;
	protected $_isCutThumb = true;

	/**
	 * @var $_thumbPrefix 缩略文件名称前缀，默认为thumb_width_height_imageFilename.jpg
	 * @var $_thumbFilename 缩略文件名 
	 */
	protected $_thumbPrefix = 'thumb_';
	protected $_thumbFilename = '';

	/**
	 * 获取缩略图文件名，如果setParams设置则直接返回，文件所在路径同来源文件路径
	 *
	 * @param string $file 来源文件全路径
	 * @return string
	 */
	public function getThumbFilename($file = '')
	{
		if ('' == $this->_thumbFilename && ''!=$file) {
			$this->_thumbFilename = $this->_thumbPrefix . $this->_thumbWidth . '_' . $this->_thumbHeight . '_';
			$pathinfo = pathinfo($file);
			$this->_thumbFilename .= $pathinfo['basename'];
		}
		if ('' == $this->_thumbFilename) {
			throw new Exception('缩略图文件名为空！');
		}
		return $this->_thumbFilename;
	}

	/**
	 * 获取缩略图全路径
	 *
	 * @return string
	 */
	public function getThumbFile()
	{
		return $this->_dir . $this->getDestFilepath() . $this->getThumbFilename();
	}

	/**
	 * 获取缩略图URL地址，绝对路径
	 *
	 * @return string
	 */
	public function getThumbFileUrl()
	{
		return $this->_host . '/' . $this->getDestFilepath() . $this->getThumbFilename();
	}

	/**
	 * 生成缩略图
	 *
	 * @param string $file 来源文件全路径
	 * @return array
	 */
	public function thumbnail($file)
	{
		//预处理缩略图文件名、路径
		$thumbFile = $this->getThumbFilename($file);
		$this->makeThumbnail($file);
		//处理水印
		if ($this->_isWatermark) {
			$this->watermark($this->getThumbFile());
		}
		//兼容性返回$ui
		return $this->getReturnFromThumb();
	}
	private function makeThumbnail($file) {
		$pathImgOld = $file;
		$pathImgNew = $this->getThumbFile();
		$newWidth     = $this->_thumbWidth;
		$newHeight     = $this->_thumbHeight;

		$Oldsize     = getimagesize($pathImgOld);
		$this->_mime = $Oldsize['mime'];
		$OldWidth     = $Oldsize[0];
		$OldHeight     = $Oldsize[1];

		$newWidth     = ($newWidth<$Oldsize[0])?$newWidth:$Oldsize[0];
		$newHeight     = ($newHeight<$Oldsize[1])?$newHeight:$Oldsize[1];
		if($OldWidth>$OldHeight){
			$newWidth = $newWidth;
			$newHeight = floor(($OldHeight/$OldWidth)*$newWidth);
		}else{
			$newHeight = $newHeight;
			$newWidth = floor(($OldWidth/$OldHeight)*$newHeight);
		}
		//处理切割
		if($this->_isCutThumb){
			$OldHeightCastr = floor(($OldWidth*$newHeight)/$newWidth);
			$castrBottom     = ($OldHeight-$OldHeightCastr)/2;

			$OldWidthCastr     = floor(($OldHeight*$newWidth)/$newHeight);
			$castrRight     = ($OldWidth-$OldWidthCastr)/2;

			if ($castrBottom>0) {
				$OldWidthCastr     = $OldWidth;
				$castrRight     = 0;
			}
			elseif ($castrRight>0) {
				$OldHeightCastr = $OldHeight;
				$castrBottom     = 0;
			}
			else {
				$OldWidthCastr     = $OldWidth;
				$OldHeightCastr = $OldHeight;
				$castrRight     = 0;
				$castrBottom     = 0;
			}
		}
		else{
			$OldWidthCastr    = $OldWidth;
			$OldHeightCastr    = $OldHeight;
			$castrRight        = 0;
			$castrBottom    = 0;
		}
		var_dump(array(
            'OldWidthCastr'=>$OldWidth,
            'OldHeightCastr'=>$OldHeight,
            'castrRight'=>0,
            'castrBottom'=>0,
		));

		$OldImg=$this->getImageReso($pathImgOld);
		$NewImgCastr=imagecreatetruecolor($OldWidthCastr,$OldHeightCastr);
		if ($NewImgCastr) {
			imagecopyresampled($NewImgCastr,$OldImg,0,0,$castrRight,$castrBottom,
			$OldWidthCastr,$OldHeightCastr,$OldWidthCastr,$OldHeightCastr);
			$NewImg=imagecreatetruecolor($newWidth,$newHeight);
			if ($NewImg) {
				imagecopyresampled($NewImg,$NewImgCastr,0,0,0,0,$newWidth,$newHeight,
				$OldWidthCastr,$OldHeightCastr);
				imagedestroy($NewImgCastr);
				imagedestroy($OldImg);
				$this->newImage($NewImg,$pathImgNew);
				imagedestroy($NewImg);
			}
		}
	}

	/**
	 * 创建新图片
	 *
	 * @param string $NewImg
	 * @param string $pathImg
	 */
	private function newImage($imageReso,$imageFile) {
		switch ($this->_mime) {
			case 'image/jpeg':
			case 'image/pjpeg':
				imagejpeg($imageReso,$imageFile,100);
				break;
			case 'image/gif':
				imagegif($imageReso,$imageFile);
				break;
			case 'image/png':
				imagepng($imageReso,$imageFile);
				break;
			case 'image/bmp':
			case 'image/x-bmp':
				$this->imagebmp($imageReso,$imageFile);
				break;
			default:
				throw new Exception('图片格式（jpeg,gif,png,bmp）不能识别！newImage()' . $imageFile);
				break;
		}
	}

	/**
	 * 从指定文件或URL创建image resourc
	 *
	 * @param string $imageFile
	 * @return resource
	 */
	private function getImageReso($imageFile)
	{
		$imageInfo = getimagesize($imageFile);
		switch ($imageInfo['mime']) {
			case 'image/jpeg':
			case 'image/pjpeg':
				$imageReso=imagecreatefromjpeg($imageFile);
				break;
			case 'image/gif':
				$imageReso=imagecreatefromgif($imageFile);
				break;
			case 'image/png':
				$imageReso=imagecreatefrompng($imageFile);
				break;
			case 'image/bmp':
			case 'image/x-bmp':
				$imageReso=$this->imagecreatefrombmp($imageFile);
				break;
			default:
				throw new Exception('图片格式（jpeg,gif,png,bmp）不能识别！getImageReso()' . $imageFile);
				break;
		}
		return $imageReso;
	}

	/**
	 * 获取水印图在目标图片上的定位
	 *
	 * @param int $w 水印图片宽
	 * @param int $h 水印图片高
	 * @param int $pos 水印位置标志，0-9的九宫位，其它值为随机位置
	 * @param resource $img
	 * @return array
	 */
	private function maskGetXY($w,$h,$pos,$img)
	{
		$ground_w = imagesx($img);
		$ground_h = imagesy($img);
		if (($ground_w<$w) || ($ground_h<$h)) {
			throw new Exception('需要加水印的图片长宽比水印还小，无法生成水印');
		}
		switch($pos) {
			case 0://随机
				$posX = rand(0,($ground_w - $w));
				$posY = rand(0,($ground_h - $h));
				break;
			case 1://1为顶端居左
				$posX = 0;
				$posY = 0;
				break;
			case 2://2为顶端居中
				$posX = ($ground_w - $w) / 2;
				$posY = 0;
				break;
			case 3://3为顶端居右
				$posX = $ground_w - $w;
				$posY = 0;
				break;
			case 4://4为中部居左
				$posX = 0;
				$posY = ($ground_h - $h) / 2;
				break;
			case 5://5为中部居中
				$posX = ($ground_w - $w) / 2;
				$posY = ($ground_h - $h) / 2;
				break;
			case 6://6为中部居右
				$posX = $ground_w - $w;
				$posY = ($ground_h - $h) / 2;
				break;
			case 7://7为底端居左
				$posX = 0;
				$posY = $ground_h - $h;
				break;
			case 8://8为底端居中
				$posX = ($ground_w - $w) / 2;
				$posY = $ground_h - $h;
				break;
			case 9://9为底端居右
				$posX = $ground_w - $w;
				$posY = $ground_h - $h;
				break;
			default://随机
				$posX = rand(0,($ground_w - $w));
				$posY = rand(0,($ground_h - $h));
				break;
		}
		return array($posX,$posY,$ground_w,$ground_h);
	}

	/**
	 * 创建bmp文件 imagecreatefrombmp($fname)
	 *
	 * @param $fname 原始文件 
	 * @return resource $img 图片资源文件
	 */
	function imagecreatefrombmp($fname)
	{
		$buf=@file_get_contents($fname);
		if(strlen($buf)<54) return false;
		$file_header=unpack("sbfType/LbfSize/sbfReserved1/sbfReserved2/LbfOffBits",substr($buf,0,14));
		if($file_header["bfType"]!=19778) return false;
		$info_header=unpack("LbiSize/lbiWidth/lbiHeight/sbiPlanes/sbiBitCountLbiCompression/LbiSizeImage/lbiXPelsPerMeter/lbiYPelsPerMeter/LbiClrUsed/LbiClrImportant",substr($buf,14,40));
		if($info_header["biBitCountLbiCompression"]==2) return false;
		$line_len=round($info_header["biWidth"]*$info_header["biBitCountLbiCompression"]/8);
		$x=$line_len%4;
		if($x>0) $line_len+=4-$x;

		$img=imagecreatetruecolor($info_header["biWidth"],$info_header["biHeight"]);
		switch($info_header["biBitCountLbiCompression"]){
			case 4:
				$colorset=unpack("L*",substr($buf,54,64));
				for($y=0;$y<$info_header["biHeight"];$y++){
					$colors=array();
					$y_pos=$y*$line_len+$file_header["bfOffBits"];
					for($x=0;$x<$info_header["biWidth"];$x++){
						if($x%2)
						$colors[]=$colorset[(ord($buf[$y_pos+($x+1)/2])&0xf)+1];
						else
						$colors[]=$colorset[((ord($buf[$y_pos+$x/2+1])>>4)&0xf)+1];
					}
					imagesetstyle($img,$colors);
					imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
				}
				break;
			case 8:
				$colorset=unpack("L*",substr($buf,54,1024));
				for($y=0;$y<$info_header["biHeight"];$y++){
					$colors=array();
					$y_pos=$y*$line_len+$file_header["bfOffBits"];
					for($x=0;$x<$info_header["biWidth"];$x++){
						$colors[]=$colorset[ord($buf[$y_pos+$x])+1];
					}
					imagesetstyle($img,$colors);
					imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
				}
				break;
			case 16:
				for($y=0;$y<$info_header["biHeight"];$y++){
					$colors=array();
					$y_pos=$y*$line_len+$file_header["bfOffBits"];
					for($x=0;$x<$info_header["biWidth"];$x++){
						$i=$x*2;
						$color=ord($buf[$y_pos+$i])|(ord($buf[$y_pos+$i+1])<<8);
						$colors[]=imagecolorallocate($img,(($color>>10)&0x1f)*0xff/0x1f,(($color>>5)&0x1f)*0xff/0x1f,($color&0x1f)*0xff/0x1f);
					}
					imagesetstyle($img,$colors);
					imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
				}
				break;
			case 24:
				for($y=0;$y<$info_header["biHeight"];$y++){
					$colors=array();
					$y_pos=$y*$line_len+$file_header["bfOffBits"];
					for($x=0;$x<$info_header["biWidth"];$x++){
						$i=$x*3;
						$colors[]=imagecolorallocate($img,ord($buf[$y_pos+$i+2]),ord($buf[$y_pos+$i+1]),ord($buf[$y_pos+$i]));
					}
					imagesetstyle($img,$colors);
					imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
				}
				break;
			default:
				for($y=0;$y<$info_header["biHeight"];$y++){
					$colors=array();
					$y_pos=$y*$line_len+$file_header["bfOffBits"];
					for($x=0;$x<$info_header["biWidth"];$x++){
						$i=$x*4;
						$colors[]=imagecolorallocate($img,ord($buf[$y_pos+$i+2]),ord($buf[$y_pos+$i+1]),ord($buf[$y_pos+$i]));
					}
					imagesetstyle($img,$colors);
					imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
				}
				break;
		}
		return $img;
	}

	/**
	 * creates a Windows BMP picture
	 *
	 * @see imagegif, imagejpeg ...
	 */
	function imagebmp(&$img, $filename=""){
		$widthOrig = imagesx($img);
		// width = 16*x
		$widthFloor = ((floor($widthOrig/16))*16);
		$widthfloor = ((floor($widthOrig/16))*16);
		$height = imagesy($img);

		$size = ($widthfloor*$height*3)+54;

		// Bitmap File Header
		$result = 'BM'; // header (2b)
		$result .= $this->int_to_dword($size); // size of file (4b)
		$result .= $this->int_to_dword(0); // reserved (4b)
		$result .= $this->int_to_dword(54);// byte location in the file which is first byte of IMAGE (4b)
		// Bitmap Info Header
		$result .= $this->int_to_dword(40);// Size of BITMAPINFOHEADER (4b)
		$result .= $this->int_to_dword($widthfloor);// width of bitmap (4b)
		$result .= $this->int_to_dword($height); // height of bitmap (4b)
		$result .= $this->int_to_word(1);// biPlanes = 1 (2b)
		$result .= $this->int_to_word(24); // biBitCount = {1 (mono) or 4 (16 clr ) or 8 (256 clr) or 24 (16 Mil)} (2b)
		$result .= $this->int_to_dword(0); // RLE COMPRESSION (4b)
		$result .= $this->int_to_dword(0); // width x height (4b)
		$result .= $this->int_to_dword(0); // biXPelsPerMeter (4b)
		$result .= $this->int_to_dword(0); // biYPelsPerMeter (4b)
		$result .= $this->int_to_dword(0); // Number of palettes used (4b)
		$result .= $this->int_to_dword(0); // Number of important colour (4b)

		// is faster than chr()
		$arrChr = array();
		for($i=0; $i<256; $i++){
			$arrChr[$i] = chr($i);
		}

		// creates image data
		$bgfillcolor = array("red"=>0, "green"=>0, "blue"=>0);

		// bottom to top - left to right - attention blue green red !!!
		$y=$height-1;
		for ($y2=0; $y2<$height; $y2++) {
			for ($x=0; $x<$widthFloor;) {
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
				$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
			}
			for ($x=$widthFloor; $x<$widthfloor; $x++) {
				$rgb = ($x<$widthOrig) ? imagecolorsforindex($img,
				imagecolorat($img, $x, $y)) : $bgfillcolor;
				$result .= $arrChr[$rgb["blue"]].$arrChr[$rgb["green"]].$arrChr[$rgb["red"]];
			}
			$y--;
		}

		// see imagegif
		if($filename==""){
			echo $result;
		} else {
			$file = fopen($filename, "wb");
			fwrite($file, $result);
			fclose($file);
		}
	}

	/**
	 * imagebmp helpers
	 *
	 */
	function int_to_dword($n){
		return chr($n & 255).chr(($n >> 8) & 255).chr(($n >> 16) & 255).chr(($n >> 24) & 255);
	}
	/**
	 * imagebmp helpers
	 *
	 */
	function int_to_word($n){
		return chr($n & 255).chr(($n >> 8) & 255);
	}

}
